package bilby;

import java.util.*;
import java.util.stream.Collectors;

import static bilby.SaveTheBilby.historyRecordAlive;
import static bilby.SaveTheBilby.historyRecordNewBorn;

/**
 * -----兔狸3个月，猫6个月，狐狸10个月（开始具备繁殖能力）--------没用上
 *
 * @author Tght
 * @date 2022/10/20
 */
public class Newborn {

    /**
     * 单位：月
     * 具备繁殖能力
     */
    public static final Integer BILBY_BORN = 3;
    public static final Integer CAT_BORN = 6;
    public static final Integer FOX_BORN = 10;

    /**
     * ①月事件一:
     * 按月创建新袋狸
     * 返回一个月后，这个地区的总袋里信息
     */
    public static Location createNewBilbyByMonth(Location location) {
        List<Bilby> bilbyArrayList = location.getBilbyArrayList().stream().filter(s -> s.isAliveStatus() == true).collect(Collectors.toList());
        String locationName = location.getName();

        // 计算出具备繁殖能力的bilby数量
        int count = 0;
        for (Bilby bilby : bilbyArrayList) {
            if (bilby.getAge() >= BILBY_BORN) {
                count++;
            }
        }
        // 新生的baby
        int newCount = 0;
        for (int i = 0; i < count; i++) {
            if (BornAt.probability(15)) {
                newCount++;
            }
        }
        // 生成一个bibly的新生儿集合
        ArrayList<Bilby> bilbyList = BornAt.careateBabyObjetc(newCount + "", locationName, true, BornAt.biblyIndex).getListBibly();
        // 新生儿和原住民拼接的集合
        ArrayList<Bilby> list = new ArrayList<>();
        for (int i = 0; i < bilbyArrayList.size() + bilbyList.size(); i++) {
            if (i < bilbyArrayList.size()) {
                Bilby bilby = bilbyArrayList.get(i);
                bilby.setNewBorn(false);
                list.add(bilby);
            } else {
                list.add(bilbyList.get(i - bilbyArrayList.size()));
            }
        }

        location.setBilbyArrayList(list);
        return location;
    }

    /**
     * ②月事件二:
     * 按月创建新猫
     */
    public static Location createNewCatByMonth(Location location) {
        List<Cat> catArrayList = location.getCatArrayList().stream().filter(s -> s.isAliveStatus() == true).collect(Collectors.toList());
        String locationName = location.getName();
        // 计算出具备繁殖能力的Cat数量
        int count = 0;
        for (Cat cat : catArrayList) {
            if (cat.getAge() >= CAT_BORN) {
                count++;
            }
        }
        // 新生的baby
        int newCount = 0;
        for (int i = 0; i < count; i++) {
            if (BornAt.probability(10)) {
                newCount++;
            }
        }
        // 生成一个bibly的新生儿集合
        ArrayList<Cat> catList = BornAt.careateBabyObjetc(newCount + "", locationName, true, BornAt.catIndex).getListCat();
        // 新生儿和原住民拼接的集合
        ArrayList<Cat> list = new ArrayList<>();
        for (int i = 0; i < catArrayList.size() + catList.size(); i++) {
            if (i < catArrayList.size()) {
                Cat cat = catArrayList.get(i);
                cat.setNewBorn(false);
                list.add(cat);
            } else {
                list.add(catList.get(i - catArrayList.size()));
            }
        }
        location.setCatArrayList(list);
        return location;
    }

    /**
     * ③月事件三:
     * 按月创建新狐狸
     */
    public static Location createNewFoxByMonth(Location location) {
        List<Fox> foxArrayList = location.getFoxArrayList().stream().filter(s -> s.isAliveStatus() == true).collect(Collectors.toList());
        String locationName = location.getName();
        // 计算出具备繁殖能力的Fox数量
        int count = 0;
        for (Fox fox : foxArrayList) {
            if (fox.getAge() >= CAT_BORN) {
                count++;
            }
        }
        // 新生的baby
        int newCount = 0;
        for (int i = 0; i < count; i++) {
            if (BornAt.probability(10)) {
                newCount++;
            }
        }
        // 生成一个bibly的新生儿集合
        ArrayList<Fox> catList = BornAt.careateBabyObjetc(newCount + "", locationName, true, BornAt.foxIndex).getListFox();
        // 新生儿和原住民拼接的集合
        ArrayList<Fox> list = new ArrayList<>();
        for (int i = 0; i < foxArrayList.size() + catList.size(); i++) {
            if (i < foxArrayList.size()) {
                Fox fox = foxArrayList.get(i);
                fox.setNewBorn(false);
                list.add(fox);
            } else {
                list.add(catList.get(i - foxArrayList.size()));
            }
        }
        location.setFoxArrayList(list);
        return location;
    }


    /**
     * ④月事件四  狐狸狩猎
     * 按月狐狸吃掉兔耳袋狸
     * 按月更新该地的狐狸和兔的存活信息
     */
    public static Location foxBehaviorByMonth(Location location) {
        List<Fox> foxes = location.getFoxArrayList();
        List<Bilby> bilbies = location.getBilbyArrayList();
        //算出当地的活兔子的数量
        int aliveBilby = 0;
        for (Bilby x : bilbies) {
            if (x.isNewBorn()) {
                aliveBilby++;
            }
        }

        Random random = new Random();
        // [0,max)
        int index = random.nextInt(bilbies.size());


        for (int i = 0; i < foxes.size() && aliveBilby > 0; i++) {
            if (BornAt.probability(40)) {
                // 吃了兔
                Bilby bilby = bilbies.get(index);
                bilby.setAliveStatus(false);
                bilbies.set(index, bilby);
                aliveBilby--;
            } else {
                // 没吃到兔
                Fox fox = foxes.get(i);
                fox.setHealthStatus(fox.getHealthStatus() - 1);
                if (fox.getHealthStatus() == 0) {
                    fox.setAliveStatus(false);
                }
                foxes.set(i, fox);
            }
        }
        location.setFoxArrayList(foxes);
        location.setBilbyArrayList(bilbies);
        return location;
    }

    /**
     * ⑤月事件五  猫狩猎
     * 按月猫吃掉兔耳袋狸
     * 按月更新该地的猫和兔的存活信息
     */
    public static Location catBehaviorByMonth(Location location) {
        List<Cat> cats = location.getCatArrayList();
        List<Bilby> bilbies = location.getBilbyArrayList();
        //算出当地的活兔子的数量
        int aliveBilby = 0;
        for (Bilby x : bilbies) {
            if (x.isNewBorn()) {
                aliveBilby++;
            }
        }

        Random random = new Random();
        // [0,max)
        int index = random.nextInt(bilbies.size());


        for (int i = 0; i < cats.size() && aliveBilby > 0; i++) {
            if (BornAt.probability(40)) {
                // 吃了兔
                Bilby bilby = bilbies.get(index);
                bilby.setAliveStatus(false);
                bilbies.set(index, bilby);
                aliveBilby--;
            } else {
                // 没吃到兔
                Cat cat = cats.get(i);
                cat.setHealthStatus(cat.getHealthStatus() - 1);
                if (cat.getHealthStatus() == 0) {
                    cat.setAliveStatus(false);
                }
                cats.set(i, cat);
            }
        }
        location.setCatArrayList(cats);
        location.setBilbyArrayList(bilbies);
        return location;
    }


    /**
     * 每月种群数量展示细节
     *
     * @param location 位置
     */
    public static void showDetailNum(Integer months, Location location, String index, Location[] locationStart, String[][] historyRecordDead) {
        // 区域总数 (生的和死的一起的数量)
        List<Cat> cats = location.getCatArrayList();
        List<Fox> foxes = location.getFoxArrayList();
        List<Bilby> bilbies = location.getBilbyArrayList();

        // 存活的
        List<Cat> cats1 = cats.stream().filter(s -> s.isAliveStatus() == true).collect(Collectors.toList());
        List<Fox> foxes1 = foxes.stream().filter(s -> s.isAliveStatus() == true).collect(Collectors.toList());
        List<Bilby> bilbies1 = bilbies.stream().filter(s -> s.isAliveStatus() == true).collect(Collectors.toList());
        int size1 = cats1.size();
        int size2 = foxes1.size();
        int size3 = bilbies1.size();

        // 新生的
        List<Cat> cats2 = cats.stream().filter(s -> s.isNewBorn() == true).collect(Collectors.toList());
        List<Fox> foxes2 = foxes.stream().filter(s -> s.isNewBorn() == true).collect(Collectors.toList());
        List<Bilby> bilbies2 = bilbies.stream().filter(s -> s.isNewBorn() == true).collect(Collectors.toList());

        int newBorn1 = cats2.size();
        int newBorn2 = foxes2.size();
        int newBorn3 = bilbies2.size();

        // 累积到当月死亡
//        List<Cat> cats3 = cats.stream().filter(s -> s.isAliveStatus() == false).collect(Collectors.toList());
//        List<Fox> foxes3 = foxes.stream().filter(s -> s.isAliveStatus() == false).collect(Collectors.toList());
//        List<Bilby> bilbies3 = bilbies.stream().filter(s -> s.isAliveStatus() == false).collect(Collectors.toList());


        // 累计到当月死亡
        int dead1 = 0;
        int dead2 = 0;
        int dead3 = 0;
        // 累计到当月死亡

        if ("month".equals(index)) {
            // 当月死亡 = 这月死亡累计 - 上月死亡累计
            String strAgo = "";
            if (months > 0) {
                strAgo = historyRecordDead[months - 1][Integer.parseInt(location.getName()) - 1];
            }
            String strNow = historyRecordDead[months][Integer.parseInt(location.getName()) - 1];
            String[] splitAgo = {"0", "0", "0"};
            if (!"".equals(strAgo)) {
                splitAgo = strAgo.split(",");
            }

            String[] splitNow = strNow.split(",");

            // 当月死亡新增 = 这月死亡累计 - 上月死亡累计
            dead1 = "".equals(splitAgo) ? Integer.parseInt(splitNow[2]) : Integer.parseInt(splitNow[2]) - Integer.parseInt(splitAgo[2]);
            dead2 = "".equals(splitAgo) ? Integer.parseInt(splitNow[1]) : Integer.parseInt(splitNow[1]) - Integer.parseInt(splitAgo[1]);
            dead3 = "".equals(splitAgo) ? Integer.parseInt(splitNow[0]) : Integer.parseInt(splitNow[0]) - Integer.parseInt(splitAgo[0]);

            printMonth(location, size1, size2, size3, newBorn1, newBorn2, newBorn3, dead1, dead2, dead3);
        }
        if ("year".equals(index)) {
            Location res = locationStart[Integer.parseInt(location.getName()) - 1];
            // 该地区初始生死总数
            List<Cat> cats4 = res.getCatArrayList();
            List<Fox> foxes4 = res.getFoxArrayList();
            List<Bilby> bilbies4 = res.getBilbyArrayList();

            months = 11;
            // 累积到当月死亡
//            String strNow = historyRecordDead[i][Integer.parseInt(location.getName()) - 1];
//            String[] split = strNow.split(",");

//
            int newBorn1C = 0;
            int newBorn2C = 0;
            int newBorn3C = 0;

            String sAlive = historyRecordAlive[months][Integer.parseInt(location.getName()) - 1];
            String[] split = sAlive.split(",");
            size1 = Integer.parseInt(split[2]);
            size2 = Integer.parseInt(split[1]);
            size3 = Integer.parseInt(split[0]);

            for (int i = 0; i < 12; i++) {

                String sNew = historyRecordNewBorn[i][Integer.parseInt(location.getName()) - 1];
                String[] split1 = sNew.split(",");
                newBorn1C += Integer.parseInt(split1[2]);
                newBorn2C += Integer.parseInt(split1[1]);
                newBorn3C += Integer.parseInt(split1[0]);
            }

            // = 出生的 - 现有的 + 原来的
            dead1 = newBorn1C - size1 + cats4.size();
            dead2 = newBorn2C - size2 + foxes4.size();
            dead3 = newBorn3C - size3 + bilbies4.size();

            printYear(location, size1, size2, size3, newBorn1C, newBorn2C, newBorn3C, dead1, dead2, dead3);
        }

    }


    public static void printMonth(Location location, int size1, int size2, int size3, int newBorn1, int newBorn2, int newBorn3, int dead1, int dead2, int dead3) {
        String alive = "地区 " + location.getName() + "\t: 存活 -> \t" + "Bilby-" + size3 + ",\tFox-" + size2 + ",\tCat-" + size1;
        String newBorn = "\t 当月新生 -> " + "Bilby-" + newBorn3 + ",\tFox-" + newBorn2 + ",\tCat-" + newBorn1;
        String dead = "\t 当月死亡 -> " + "Bilby-" + dead3 + ",\tFox-" + dead2 + ",\tCat-" + dead1;
        System.out.println(alive + "\t\t" + newBorn + "\t\t" + dead);
    }

    public static void printYear(Location location, int size1, int size2, int size3, int newBorn1, int newBorn2, int newBorn3, int dead1, int dead2, int dead3) {
        String area = "地区" + location.getName() + "\n";
        String aliveAnimals = "alive: bilby-" + size3 + " " + "fox-" + size2 + " " + "cat-" + size1 + "\n";
        String newBorn = "newBorn: bilby-" + newBorn3 + " " + "fox-" + newBorn2 + " " + "cat-" + newBorn1 + "\n";
        String dead = "dead: bilby-" + dead3 + " " + "fox-" + dead2 + " " + "cat-" + dead1 + "\n";
        System.out.println(area + aliveAnimals + newBorn + dead);
    }

    /**
     * 调查10个地区兔耳袋狸的数量
     * 返回一个list，元素是map<Location,Integr>
     */
    public static List<Map.Entry<Location, Integer>> getBilbyNumEveryLocation(Location[] locations) {
        Map<Location, Integer> emptyLocation = new HashMap<>();
        for (int i = 0; i < locations.length; i++) {
            int aliveSize = locations[i].getBilbyArrayList().stream().filter(s -> s.isAliveStatus() == true).collect(Collectors.toList()).size();
            if (aliveSize < 20) {
                emptyLocation.put(locations[i], 20 - aliveSize);
            }
        }

        // 排序得到一个空位置从大到小的集合
        ArrayList<Map.Entry<Location, Integer>> arrayList = new ArrayList<>(emptyLocation.entrySet());

        Collections.sort(arrayList, new Comparator<Map.Entry<Location, Integer>>() {
            public int compare(Map.Entry<Location, Integer> map1, Map.Entry<Location, Integer> map2) {
                return (map2.getValue() - map1.getValue());
            }
        });
        //按照剩余空间多少降序排序
        return arrayList;
    }

    /**
     * 实现 物种迁徙 的底层方法
     */
    public static Location[] SpeciesMigration(List<Bilby> bilbies, Location[] locations) {
        List<Map.Entry<Location, Integer>> entryList = getBilbyNumEveryLocation(locations);
        if (entryList.size() == 0) {
            return locations;// 实在没地方放了，得弄死
        }
        // 需要迁移的数量
        int size = bilbies.size();
        int index = 0;
        do {
            // 在当前地区能迁徙的数量
            int num = 0;
            // 当前迁徙目的地区
            Location key = entryList.get(index).getKey();
            if (size < entryList.get(index).getValue()) {
                //一次就好
                num = size;
            } else {
                //还要再迁徙
                num = entryList.get(index).getValue();
            }

            for (int i = 0; i < num; i++) {
                Bilby bilby = bilbies.get(i);
                bilby.setLocation(key.getName());
                List<Bilby> bilbyList = key.getBilbyArrayList();
                bilbyList.add(bilby);
                key.setBilbyArrayList(bilbyList);
            }

            locations[Integer.parseInt(key.getName()) - 1] = key;

            size -= num;
            index++;
            if (index > entryList.size()) {
                System.out.println("已经没有剩余的地方可供生存了");
                // 拿到家乡信息 落叶归根
                Location location = locations[Integer.parseInt(key.getName()) - 1];
                List<Bilby> list = location.getBilbyArrayList();
                for (int i = bilbies.size() - size; i < bilbies.size(); i++) {
                    Bilby bilby = bilbies.get(i);
                    bilby.setAliveStatus(false);
                    list.add(bilby);
                }
                location.setBilbyArrayList(list);
                locations[Integer.parseInt(key.getName()) - 1] = location;
                return locations;
            }
        } while (size > 0);

        return locations;
    }


    /**
     * ⑥干预一:迁徙
     * 有20只才调用这个方法
     */
    public static Location[] interventionOneMigration(Location location, Boolean isLiveOrDead, Location[] locations) {
        // 土著兔
        List<Bilby> bilbyList = location.getBilbyArrayList().stream().filter(s -> s.isAliveStatus() == true).collect(Collectors.toList());
        List<Bilby> bilbyListTotal = location.getBilbyArrayList();
        // 迁徙的兔
        List<Bilby> bilbies = new ArrayList<>();
        // 从21只开始接受变化
        for (int i = 0; i < bilbyList.size() - 20; i++) {
            bilbies.add(bilbyList.get(i));
        }

        if (isLiveOrDead) {
            // 迁徙
            ArrayList<String> list = new ArrayList<>();
            for (int i = 0; i < bilbyList.size() - 20; i++) {
                list.add(bilbyList.get(i).getCode());
            }
            // 拿到编号后
            for (int i = 0; i < list.size(); i++) {
                for (int j = 0; j < bilbyListTotal.size(); j++) {
                    if (list.get(i).equals(bilbyListTotal.get(j).getCode())) {
                        // 匹配编号，执行删除
                        bilbyListTotal.remove(j);
                    }
                }
            }

            // 更新原住民
            location.setBilbyArrayList(bilbyListTotal);
            locations[Integer.parseInt(location.getName()) - 1] = location;
            // 即将出行，全局信息
            return SpeciesMigration(bilbies, locations);
        } else {
            // 准备死亡，从活的里面拿到超出的编码
            ArrayList<String> list = new ArrayList<>();
            for (int i = 0; i < bilbyList.size() - 20; i++) {
                list.add(bilbyList.get(i).getCode());
            }
            // 拿到编号后
            for (int i = 0; i < list.size(); i++) {
                for (int j = 0; j < bilbyListTotal.size(); j++) {
                    if (list.get(i).equals(bilbyListTotal.get(j).getCode())) {
                        // 匹配编号，执行死刑
                        Bilby bilby = bilbyListTotal.get(j);
                        bilby.setAliveStatus(false);
                        bilbyListTotal.set(j, bilby);
                        break;
                    }
                }
            }

            // 更新原住民
            location.setBilbyArrayList(bilbyListTotal);
            locations[Integer.parseInt(location.getName()) - 1] = location;
            return locations;
        }
    }


    /**
     * ⑦干预二:屠杀
     * 屠魔令
     */
    public static Location updateEnemy(Location location) {
        List<Fox> foxes = location.getFoxArrayList();
        List<Cat> cats = location.getCatArrayList();

        for (int i = 0; i < foxes.size(); i++) {
            Fox fox = foxes.get(i);
            if (BornAt.probability(50)) {
                fox.setAliveStatus(false);
                fox.setHealthStatus(0);
                foxes.set(i, fox);
            }
        }

        for (int i = 0; i < cats.size(); i++) {
            Cat cat = cats.get(i);
            if (BornAt.probability(50)) {
                cat.setAliveStatus(false);
                cat.setHealthStatus(0);
                cats.set(i, cat);
            }
        }

        location.setFoxArrayList(foxes);
        location.setCatArrayList(cats);
        return location;
    }


}
